#include "srandser.h"


SrandSvr::SrandSvr()
{
    IndexAndStuNameVec_.clear();
    FileOper_ = NULL;
    Indexformap_ = -1;
}

SrandSvr::~SrandSvr()
{
    if(!FileOper_)
    {
        delete FileOper_;
    }
}

int SrandSvr::OnInit(const string& ConfigName, const string& CyclCount)
{
    //创建file操作对象
    FileOper_ = new FileOperSer();
    if(!FileOper_)
    {
        perror("创建文件指针对象失败");
        return -1;
    }
    //目前的做法是直接写死了文件的名称，讲道理这个可以提供一个配置文件，然后从配置文件中读出来，或者后期增加了http服务之后，从网页的返回中拉取回来
    int ret = FileOper_->OnInit(ConfigName);
    if(ret != 0)
    {
        printf("SrandSvr::OnInit %d\n", __LINE__);
        return -1;
    }
    //学生数据初始化
    return 0;
}

string SrandSvr::CalcRandName(int Randcount)
{
    string retvalue = "";
    if(Randcount <= 0)
    {
        printf("SrandSvr::CalcRandName Randcount<=0 %s:%d\n", __FILE__, __LINE__);
        return retvalue;
    }
    //这个vector是用来装 预随机出来的人，下面的逻辑中会使用该vector去选择最终的随机出来的人
    //随机的规则是，谁缺课最多就选择谁，如果还没有在的话，就选择次大的
    //如果人数是一直的就返回第一个选择到的
    for(int i = 0; i < Randcount; i++)
    {
        int StuInfoMapSize = FileOper_->GetMapSize() - i;
        if(StuInfoMapSize <= 0 && i == 0)
        {
            printf("已经没有童鞋可以随机抽取了\n");
            return retvalue;
        }

        if(StuInfoMapSize <= 0)
        {
            break;
        }

        //开始计算下标
        srand(time(0));
        int tmpcount = rand() % StuInfoMapSize;
        StuInfo si;
        IndexAndStuName indexname;
        int ret = FileOper_->FindFromMap(tmpcount, &si);
        if(ret != 0)
        {
            GetErrorFileAndNum::Printf();
            return retvalue;
        }
        indexname.Index_ = tmpcount;
        indexname.si = si;
        IndexAndStuNameVec_.push_back(indexname);
    }

    return InnerCalcRandName();
}

int SrandSvr::JudgeStuName(const string& StuName)
{

    if(StuName.size() <= 0)
    {
        printf("预选择的同学都没有来，太遗憾了\n");
        WriteToFile();
        return -1;
    }

    printf("恭喜 %s 童鞋\n", StuName.c_str());
    printf("该同学是否存在呢？：");
    string IsExist = "y";
    cin >> IsExist;
    if(IsExist == "y" || IsExist == "Y")
    {
        //这边没有什么要处理的
       FileOper_->UpdateMapData(Indexformap_, true);
    }
    else if(IsExist == "n" || IsExist == "N")
    {
        //修改map中的没有来的次数 +1
       int ret = FileOper_->UpdateMapData(Indexformap_, false);
       if(ret != 0)
       {
           GetErrorFileAndNum();
           return -1;
       }
       //先把该同学从预选择的vec中删除掉
       //然后从预选择的vec中在选择一个
       
       auto itor = IndexAndStuNameVec_.begin();
       while(itor != IndexAndStuNameVec_.end())
       {
           if(itor->si.StuName == StuName)
           {
               itor = IndexAndStuNameVec_.erase(itor);
           }
           else
           {
               itor++;
           }
       }

       JudgeStuName(InnerCalcRandName());
    }
    else
    {

    }
    WriteToFile();
    return 0;
}

string SrandSvr::InnerCalcRandName()
{
    if(IndexAndStuNameVec_.size() <= 0)
    {
        return "";
    }

    auto itor = IndexAndStuNameVec_.begin();
    string MaxCount = itor->si.OutOfClassCount;
    //增加一个临时变量作为函数的返回值
    string StuName = itor->si.StuName;
    Indexformap_ = itor->Index_;
    while(itor != IndexAndStuNameVec_.end())
    {
        if(atoi(MaxCount.c_str()) < atoi(itor->si.OutOfClassCount.c_str()))
        {
            MaxCount = itor->si.OutOfClassCount;
            StuName = itor->si.StuName;
            Indexformap_ = itor->Index_;
        }
        itor++;
    }
    //这里一定不能返回itor，itor已经指向了vector的最后了
    return StuName;
}

void SrandSvr::ShowStuData()
{
    if(FileOper_)
    {
        FileOper_->ShowAllDataFromMap();
    }
}

int SrandSvr::WriteToFile()
{
    int ret = 0;
    if(FileOper_)
    {
        ret = FileOper_->WriteToFile();
    }
    return ret;
}


void PrintHelp()
{
    printf("./srandsvr -configfile [configfile] -count [cyclecount]\n");
}

int main(int argc, char* argv[])
{
    if(argc != 5)
    {
        PrintHelp();
        return 0;
    }
    string ConfigName = "";
    string CyclCount = "";
    for(int i = 0; i < argc; i++)
    {
        if(strcmp(argv[i], "-configfile") == 0)
        {
            ConfigName = argv[i+1];
        }
        else if(strcmp(argv[i], "-count") == 0)
        {
            CyclCount = argv[i+1];
        }
    }

    if(ConfigName.size() <= 0 || CyclCount.size() <= 0)
    {
        PrintHelp();
        return 0;
    }

    SrandSvr ss; 
    int ret = 0;
    ret = ss.OnInit(ConfigName, CyclCount);
    if(ret != 0)
    {
        printf("main:SrandSvr OnInit Failed\n");
        return 0;
    }
    string RandName = ss.CalcRandName(atoi(CyclCount.c_str()));
    if(RandName.size() <= 0)
    {
        printf("main:RandName Failed\n");
        return 0;
    }
    ret = ss.JudgeStuName(RandName);
    if(ret != 0)
    {
        printf("main:随机出错\n");
        return 0;
    }
    ss.ShowStuData();
    return 0;
}
